home *** CD-ROM | disk | FTP | other *** search
/ Speccy ClassiX 1998 / Speccy ClassiX 98.iso / amiga_system / the_aminet / dev / gcc / ixemulsrc.lha / ixemul-41.4 / library / statfs.c < prev    next >
C/C++ Source or Header  |  1995-05-28  |  10KB  |  366 lines

  1. /*
  2.  *  This file is part of ixemul.library for the Amiga.
  3.  *  Copyright (C) 1991, 1992  Markus M. Wild
  4.  *
  5.  *  This library is free software; you can redistribute it and/or
  6.  *  modify it under the terms of the GNU Library General Public
  7.  *  License as published by the Free Software Foundation; either
  8.  *  version 2 of the License, or (at your option) any later version.
  9.  *
  10.  *  This library is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.  *  Library General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU Library General Public
  16.  *  License along with this library; if not, write to the Free
  17.  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  *
  19.  *  statfs.c,v 1.1.1.1 1994/04/04 04:31:00 amiga Exp
  20.  *
  21.  *  statfs.c,v
  22.  * Revision 1.1.1.1  1994/04/04  04:31:00  amiga
  23.  * Initial CVS check in.
  24.  *
  25.  *  Revision 1.2  1992/08/09  21:00:32  amiga
  26.  *  add alternate fs id's...
  27.  *
  28.  *  Revision 1.1  1992/05/22  01:50:27  mwild
  29.  *  Initial revision
  30.  *
  31.  */
  32.  
  33. #define KERNEL
  34. #include "ixemul.h"
  35. #include "kprintf.h"
  36. #include <sys/mount.h>
  37.  
  38. #ifndef ID_FFS_DISK
  39. #define ID_FFS_DISK        (0x444F5301L)    /* 'DOS\1' */
  40. #define ID_INTER_DOS_DISK    (0x444F5302L)    /* 'DOS\2' */
  41. #define ID_INTER_FFS_DISK    (0x444F5303L)    /* 'DOS\3' */
  42. #define ID_MSDOS_DISK        (0x4d534400L)    /* 'MSD\0' */
  43. #endif
  44.  
  45. /* no comments here ;-) */
  46. #define ID_ALT_OFS_DISK        (0x444F5304L)    /* 'DOS\4' */
  47. #define ID_ALT_FFS_DISK        (0x444F5305L)    /* 'DOS\5' */
  48. #define ID_ALT_INTER_DOS_DISK    (0x444F5306L)    /* 'DOS\6' */
  49. #define ID_ALT_INTER_FFS_DISK    (0x444F5307L)    /* 'DOS\7' */
  50.  
  51.  
  52. /* this function fills in InfoData information from a statfs structure
  53.    that has at least its f_fsid field set to the handler */
  54.  
  55. static void
  56. internal_statfs (struct statfs *buf, struct InfoData *info, struct StandardPacket *sp)
  57. {
  58.   sp->sp_Pkt.dp_Port = u.u_sync_mp;
  59.   sp->sp_Pkt.dp_Type = ACTION_DISK_INFO;
  60.   sp->sp_Pkt.dp_Arg1 = CTOBPTR (info);
  61.   PutPacket ((struct MsgPort *) buf->f_fsid.val[0], sp);
  62.   __wait_sync_packet (sp);
  63.       
  64.   /* if packet is implemented on handler side */
  65.   if (sp->sp_Pkt.dp_Res1 == -1)
  66.     {
  67.       struct DeviceList *dl = BTOCPTR (info->id_VolumeNode);
  68.  
  69.       if (dl)
  70.     {
  71.           char *name = BTOCPTR (dl->dl_Name);
  72.       int len = (MNAMELEN - 2 < name[0]) ? MNAMELEN - 2 : name[0];
  73.  
  74.       /* use this field to represent the volume name */
  75.           bcopy (name + 1, buf->f_mntfromname + 1, len);
  76.           buf->f_mntfromname[0] = '/';
  77.           buf->f_mntfromname[len + 1] = 0;
  78.         }
  79.       else
  80.     /* for stuff like FIFO that doesn't have an associated volume */
  81.     strcpy (buf->f_mntfromname, buf->f_mntonname);
  82.  
  83.       switch (info->id_DiskType)
  84.         {
  85.         case ID_DOS_DISK:
  86.         case ID_ALT_OFS_DISK:
  87.           buf->f_type = MOUNT_ADOS_OFS;
  88.       break;
  89.           
  90.     case ID_FFS_DISK:
  91.     case ID_ALT_FFS_DISK:
  92.       buf->f_type = MOUNT_ADOS_FFS;
  93.       break;
  94.  
  95.     case ID_INTER_DOS_DISK:
  96.     case ID_ALT_INTER_DOS_DISK:
  97.       buf->f_type = MOUNT_ADOS_IOFS;
  98.       break;
  99.  
  100.     case ID_INTER_FFS_DISK:
  101.     case ID_ALT_INTER_FFS_DISK:
  102.       buf->f_type = MOUNT_ADOS_IFFS;
  103.       break;
  104.  
  105.     case ID_MSDOS_DISK:
  106.       buf->f_type = MOUNT_PC;
  107.       break;
  108.       
  109.     case 'NFS\0':    /* dunno, would be logical ;-)) */
  110.       buf->f_type = MOUNT_NFS;
  111.       break;
  112.       
  113.     case 'UFS\0':    /* did somebody already do this ??? */
  114.       buf->f_type = MOUNT_UFS;
  115.       break;
  116.  
  117.     default:          
  118.       buf->f_type = MOUNT_NONE;
  119.       break;
  120.     }
  121.         
  122.       buf->f_flags  = MNT_NOSUID | MNT_NODEV;
  123.       if (info->id_DiskState != ID_VALIDATED)
  124.         /* can be ID_WRITE_PROTECTED or ID_VALIDATING */
  125.     buf->f_flags |= MNT_RDONLY;
  126.         
  127.       buf->f_fsize  = info->id_BytesPerBlock;
  128.       buf->f_bsize  = info->id_BytesPerBlock * ix.ix_fs_buf_factor;
  129.       buf->f_blocks = info->id_NumBlocks;
  130.       buf->f_bfree =
  131.         buf->f_bavail = info->id_NumBlocks - info->id_NumBlocksUsed;
  132.       /* no inode information available, thus set to -1 */
  133.       buf->f_files =
  134.       buf->f_ffree = -1;
  135.    }
  136. }
  137.  
  138.  
  139.  
  140. int
  141. getfsstat (struct statfs *buf, long bufsize, int flags)
  142. {
  143.   int num_devs = 0;
  144.   struct statfs *orig_buf = buf;
  145.   long orig_bufsize = bufsize;
  146.   
  147.   struct DosLibrary *dl;
  148.   struct RootNode *rn;
  149.   struct DosInfo *di;
  150.   struct DevInfo *dv;
  151.   extern struct ixemul_base *ixemulbase;
  152.   
  153.   struct InfoData *info;
  154.   struct StandardPacket *sp;
  155.  
  156.   /* could probably use less drastic measures under 2.0... */
  157.   Forbid ();
  158.   dl = (struct DosLibrary *) ixemulbase->ix_dos_base;
  159.   rn = (struct RootNode *) dl->dl_Root;
  160.   di = BTOCPTR (rn->rn_Info);
  161.   for (dv = BTOCPTR (di->di_DevInfo); dv; dv = BTOCPTR (dv->dvi_Next))
  162.     {
  163.       if (dv->dvi_Type == DLT_DEVICE && dv->dvi_Task && dv->dvi_Name)
  164.     {
  165.       num_devs ++;
  166.       if (buf && bufsize >= sizeof (*buf))
  167.         {
  168.           char *name = BTOCPTR (dv->dvi_Name);
  169.           int len = (MNAMELEN - 2 < name[0]) ? MNAMELEN - 2 : name[0];
  170.  
  171.           /* only remember the name and the address of the
  172.              handler so that we can later send INFO packets there */
  173.           bzero (buf, sizeof (*buf));
  174.           bcopy (name + 1, buf->f_mntonname + 1, len);
  175.           buf->f_mntonname[0] = '/';
  176.           buf->f_mntonname[len + 1] = 0;
  177.           buf->f_fsid.val[1] = 0;
  178.           buf->f_fsid.val[0] = (long) dv->dvi_Task;
  179.           
  180.           buf++;
  181.           bufsize -= sizeof (struct statfs);
  182.         }
  183.     }
  184.     }
  185.   Permit ();
  186.  
  187.   if (! orig_buf || orig_bufsize < sizeof (struct statfs))
  188.     return num_devs;
  189.  
  190.   info = alloca (sizeof (*info) + 2);
  191.   info = LONG_ALIGN (info);
  192.  
  193.   sp = alloca (sizeof (*sp) + 2);
  194.   sp = LONG_ALIGN (sp);
  195.   __init_std_packet (sp);
  196.  
  197.   /* have a second run, and inquire more data from the associated volumes */
  198.   while (orig_buf < buf)
  199.     {
  200.       internal_statfs (orig_buf, info, sp);
  201.       orig_buf++;
  202.     }
  203.  
  204.   return num_devs;
  205. }
  206.  
  207. int
  208. fstatfs (int fd, struct statfs *buf)
  209. {
  210.   struct file *f = u.u_ofile[fd];
  211.   struct DosLibrary *dl;
  212.   struct RootNode *rn;
  213.   struct DosInfo *di;
  214.   struct DevInfo *dv;
  215.   extern struct ixemul_base *ixemulbase;
  216.   
  217.   struct InfoData *info;
  218.   struct StandardPacket *sp;
  219.  
  220.   if ((unsigned)fd < NOFILE && f)
  221.     {
  222.       if (! buf)
  223.         {
  224.           errno = EFAULT;
  225.       KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  226.           return -1;
  227.         }
  228.  
  229.       if (HANDLER_NIL (f) || f->f_type != DTYPE_FILE)
  230.         {
  231.           errno = EOPNOTSUPP;
  232.       KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  233.       return -1;
  234.     }
  235.  
  236.       bzero (buf, sizeof (struct statfs));
  237.       buf->f_fsid.val[1] = 0;
  238.       buf->f_fsid.val[0] = (long) f->f_fh->fh_Type;
  239.       /* could probably use less drastic measures under 2.0... */
  240.       Forbid ();
  241.       dl = (struct DosLibrary *) ixemulbase->ix_dos_base;
  242.       rn = (struct RootNode *) dl->dl_Root;
  243.       di = BTOCPTR (rn->rn_Info);
  244.       for (dv = BTOCPTR (di->di_DevInfo); dv; dv = BTOCPTR (dv->dvi_Next))
  245.         {
  246.           if (dv->dvi_Type == DLT_DEVICE && 
  247.           (struct MsgPort *) dv->dvi_Task == f->f_fh->fh_Type)
  248.         {
  249.           char *name = BTOCPTR (dv->dvi_Name);
  250.           int len = (MNAMELEN - 2 < name[0]) ? MNAMELEN - 2 : name[0];
  251.  
  252.           bcopy (name + 1, buf->f_mntonname + 1, len);
  253.           buf->f_mntonname[0] = '/';
  254.           buf->f_mntonname[len + 1] = 0;
  255.           break;
  256.         }
  257.     }
  258.       Permit ();
  259.  
  260.       if (! dv)
  261.     {
  262.       errno = EOPNOTSUPP;
  263.       KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  264.           return -1;
  265.         }
  266.  
  267.       info = alloca (sizeof (*info) + 2);
  268.       info = LONG_ALIGN (info);
  269.  
  270.       sp = alloca (sizeof (*sp) + 2);
  271.       sp = LONG_ALIGN (sp);
  272.       __init_std_packet (sp);
  273.  
  274.       internal_statfs (buf, info, sp);
  275.  
  276.       return 0;
  277.     }
  278.     
  279.   errno = EBADF;  
  280.   KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  281.   return -1;
  282. }
  283.  
  284.  
  285. int
  286. statfs (const char *path, struct statfs *buf)
  287. {
  288.   struct MsgPort *handler;
  289.   BPTR lock;
  290.   int omask, err;
  291.   struct DosLibrary *dl;
  292.   struct RootNode *rn;
  293.   struct DosInfo *di;
  294.   struct DevInfo *dv;
  295.   extern struct ixemul_base *ixemulbase;
  296.   
  297.   struct InfoData *info;
  298.   struct StandardPacket *sp;
  299.  
  300.   omask = syscall (SYS_sigsetmask, ~0);
  301.   lock = __lock (path, ACCESS_READ);
  302.   handler = lock ? ((struct FileLock *) BTOCPTR (lock))->fl_Task : 0;
  303.   err = __ioerr_to_errno (IoErr ());
  304.   if (lock)
  305.     __unlock (lock);
  306.   syscall (SYS_sigsetmask, omask);
  307.   
  308.   if (! handler)
  309.     {
  310.       errno = err;
  311.       KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  312.       return -1;
  313.     }
  314.   else
  315.     {
  316.       if (! buf)
  317.         {
  318.           errno = EFAULT;
  319.       KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  320.           return -1;
  321.         }
  322.  
  323.       bzero (buf, sizeof (struct statfs));
  324.       buf->f_fsid.val[1] = 0;
  325.       buf->f_fsid.val[0] = (long) handler;
  326.       /* could probably use less drastic measures under 2.0... */
  327.       Forbid ();
  328.       dl = (struct DosLibrary *) ixemulbase->ix_dos_base;
  329.       rn = (struct RootNode *) dl->dl_Root;
  330.       di = BTOCPTR (rn->rn_Info);
  331.       for (dv = BTOCPTR (di->di_DevInfo); dv; dv = BTOCPTR (dv->dvi_Next))
  332.         {
  333.           if (dv->dvi_Type == DLT_DEVICE && 
  334.           (struct MsgPort *) dv->dvi_Task == handler)
  335.         {
  336.           char *name = BTOCPTR (dv->dvi_Name);
  337.           int len = (MNAMELEN - 2 < name[0]) ? MNAMELEN - 2 : name[0];
  338.  
  339.           bcopy (name + 1, buf->f_mntonname + 1, len);
  340.           buf->f_mntonname[0] = '/';
  341.           buf->f_mntonname[len + 1] = 0;
  342.           break;
  343.         }
  344.     }
  345.       Permit ();
  346.  
  347.       if (! dv)
  348.     {
  349.       errno = EOPNOTSUPP;
  350.       KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  351.           return -1;
  352.         }
  353.  
  354.       info = alloca (sizeof (*info) + 2);
  355.       info = LONG_ALIGN (info);
  356.  
  357.       sp = alloca (sizeof (*sp) + 2);
  358.       sp = LONG_ALIGN (sp);
  359.       __init_std_packet (sp);
  360.  
  361.       internal_statfs (buf, info, sp);
  362.  
  363.       return 0;
  364.     }
  365. }
  366.